/** @file    posix/processes.cpp
 *  @author  Alessandro Polo
 *  @version $Id: processes.cpp 2287 2010-04-08 15:15:57Z alex $
 *  @brief   multi-platform implementation of process-related functions.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#include "processes.h"

#include <sys/types.h>
#include <unistd.h>
#include <ios>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

//////////////////////////////////////////////////////////////////////////////
long getCurrentProcessPID() {
	return (long)getpid();
 }

//////////////////////////////////////////////////////////////////////////////
long getParentProcessPID() {
	return (long)getppid();
 }

//////////////////////////////////////////////////////////////////////////////
bool retrieveProcessInfo( long, map<string, string>& fields ) {
	using std::ios_base;
	using std::ifstream;
	using std::string;

	// 'file' stat seems to give the most reliable results
	ifstream stat_stream("/proc/self/stat",ios_base::in);

	// dummy vars for leading entries in stat that we don't care about
	string pid, comm, state, ppid, pgrp, session, tty_nr;
	string tpgid, flags, minflt, cminflt, majflt, cmajflt;
	string utime, stime, cutime, cstime, priority, nice;
	string O, itrealvalue, starttime;

	// the two fields we want
	unsigned long vsize = 0;
	long rss = 0;

	stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
				>> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
				>> utime >> stime >> cutime >> cstime >> priority >> nice
				>> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest

	fields["SysInfo_stat_pid"] = pid;
	fields["SysInfo_stat_comm"] = comm;
	fields["SysInfo_stat_state"] = state;
	fields["SysInfo_stat_ppid"] = ppid;
	fields["SysInfo_stat_pgrp"] = pgrp;
	fields["SysInfo_stat_session"] = session;
	fields["SysInfo_stat_tty_nr"] = tty_nr;
	fields["SysInfo_stat_tpgid"] = tpgid;
	fields["SysInfo_stat_flags"] = flags;
	fields["SysInfo_stat_minflt"] = minflt;
	fields["SysInfo_stat_cminflt"] = cminflt;
	fields["SysInfo_stat_majflt"] = majflt;
	fields["SysInfo_stat_cmajflt"] = cmajflt;
	fields["SysInfo_stat_utime"] = utime;
	fields["SysInfo_stat_stime"] = stime;
	fields["SysInfo_stat_cutime"] = cutime;
	fields["SysInfo_stat_cstime"] = cstime;
	fields["SysInfo_stat_priority"] = priority;
	fields["SysInfo_stat_nice"] = nice;
	fields["SysInfo_stat_O"] = O;
	fields["SysInfo_stat_itrealvalue"] = itrealvalue;
	fields["SysInfo_stat_starttime"] = starttime;

	long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
	long vm_usage = vsize / 1024.0;
	long resident_set = rss * page_size_kb;
	char buffer [33];
	sprintf(buffer,"%li",vm_usage);
	fields["SysInfo_VirtualMemorySize"] = string(buffer);
	sprintf(buffer,"%li",resident_set);
	fields["SysInfo_ResidentSetSize"] = string(buffer);
	return true;
 }
